import pandas as pd
from sqlalchemy.types import VARCHAR,INTEGER,DECIMAL,FLOAT

def __col_to_str(df,cols):
    df[cols] = df[cols].astype("str")
    return df

def merge_df(df1, df2, cols,how='inner'):
    """
        This function is used to merge two tables

        Parameters:
          df_name1 - The name of DataFrame1.
          df_name2 - The name of DataFrame2.
          cols - The name(s) of the columns to be merged

        Raises:
          KeyError - Can't find the target column in DataFrame.
    """
    if isinstance(cols,list) and len(cols) == 2 and isinstance(cols[0],list) and isinstance(cols[1],list):
        left_cols = cols[0]
        right_cols = cols[1]
    else:
        left_cols = cols
        right_cols = cols
    return pd.merge(__col_to_str(df1,left_cols), __col_to_str(df2,right_cols),how = how,left_on = left_cols,right_on = right_cols)

def replaceColumn(str_old,cols,repCols):
    str_new = str_old
    if isinstance(cols, list) and isinstance(repCols,list):
        for i in range(len(cols)):
            if isinstance(cols[i], str) and isinstance(repCols[i], str):
                str_new = str_new.replace(cols[i],repCols[i])
    elif isinstance(cols, str) and isinstance(repCols,str):
        str_new = str_new.replace(cols, repCols)
    return str_new

def __isGrouped(df):
    """
        This function is used to determine whether the data source
        is a grouping result.

        Parameters:
          df - The DataFrame to judge.

        Returns:
          The judge result.
    """
    return isinstance(df, pd.core.groupby.groupby.DataFrameGroupBy)

def distinct_df(df,cols=[],df_name=None):
    if __isGrouped(df):
        return df.apply(distinct_df, cols, df_name)
    elif len(cols) == 0:
        return df.drop_duplicates()
    elif len(cols) > 0 and df_name is not None:
        return df.drop_duplicates(cols)

def get_dict_type(df):
    type_dict = {}
    for col in df.columns:
        tp = df[col].dtype
        if 'object' in str(tp) :
            type_dict[col] = VARCHAR()
            df[col] = df[col].apply(lambda x: '' if x is None else str(x))
        elif 'int' in str(tp):
            type_dict[col] = INTEGER()
        elif 'float' in str(tp):
            type_dict[col] = FLOAT()
        else:
            type_dict[col] = VARCHAR()
    return type_dict